package promotion

import (
	sqlc "bp/db/sqlc"
	"bp/internal/render"
	nsqMall "bp/internal/service/com/nsqMall"
	nsqPay "bp/internal/service/com/nsqPay"
	"bp/internal/util"
	messageGrpc "bp/rpc/gen/shared/message"
	"context"
	"encoding/json"
	"github.com/golang/protobuf/ptypes/empty"
)

// ExpireCoupons 过期优惠券
func (s *CronWebApiImp) ExpireCoupons(ctx context.Context, _ *empty.Empty) (res *messageGrpc.CronRes, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("cron_imp/cron.ExpireCoupons")
	defer render.FriendlyEntityError(&err, EntityName)
	res = &messageGrpc.CronRes{}

	var limit int32 = 100
	q := s.dao.Q
	// 这里是单一原子不做多个语句的事务
	err = s.entityHub.CouponService.ExpireCoupons(ctx, q, limit)
	if err != nil {
		return
	}

	res.Msg = "ok"
	return
}

// ExpireMemberCoupons 过期会员优惠券
func (s *CronWebApiImp) ExpireMemberCoupons(ctx context.Context, _ *empty.Empty) (res *messageGrpc.CronRes, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("cron_imp/cron.ExpireMemberCoupons")
	defer render.FriendlyEntityError(&err, EntityName)
	res = &messageGrpc.CronRes{}

	var limit int32 = 100
	q := s.dao.Q
	// 这里是单一原子不做多个语句的事务
	err = s.entityHub.MemberCouponService.ExpireMemberCoupons(ctx, q, limit)
	if err != nil {
		return
	}

	res.Msg = "ok"
	return
}

// ExpirePromotions 过期促销活动
func (s *CronWebApiImp) ExpirePromotions(ctx context.Context, _ *empty.Empty) (res *messageGrpc.CronRes, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("cron_imp/cron.ExpirePromotions")
	defer render.FriendlyEntityError(&err, EntityName)
	res = &messageGrpc.CronRes{}

	var limit int32 = 100
	q := s.dao.Q
	// 这里是单一原子不做多个语句的事务
	err = s.entityHub.PromotionService.ExpirePromotions(ctx, q, limit)
	if err != nil {
		return
	}

	res.Msg = "ok"
	return
}

// PublishNsqs 发布Nsq消息
func (s *CronWebApiImp) PublishNsqs(ctx context.Context, _ *empty.Empty) (res *messageGrpc.CronRes, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("cron_imp/cron.PublishNsqs")
	defer render.FriendlyEntityError(&err, EntityName)
	res = &messageGrpc.CronRes{}

	var limit int32 = 10
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		nsqPubPtrs, err := s.entityHub.NsqService.ListNsqPubPtrsWithLock(ctx, q, limit)
		if err != nil {
			return
		}
		for _, nsqPubPtr := range nsqPubPtrs {
			nsqPubPtrID := nsqPubPtr.ID
			err = s.pub.PublishNotification(nsqPubPtr)
			if err != nil {
				upErr := s.entityHub.NsqService.UpdateNsqPubError(ctx, q, nsqPubPtrID, err.Error())
				if upErr != nil {
					return
				}
			}
			err = s.entityHub.NsqService.MarkNsqPubSendSuccess(ctx, q, nsqPubPtrID)
			if err != nil {
				return
			}
		}
		slog.Infof("nsqPubPtrs (%d)条", len(nsqPubPtrs))
		return
	})
	if err != nil {
		return
	}
	res.Msg = "ok"
	return
}

// HandleCompensationSubscribedNsqs 处理补偿的订阅的消息
func (s *CronWebApiImp) HandleCompensationSubscribedNsqs(ctx context.Context, _ *empty.Empty) (res *messageGrpc.CronRes, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("cron_imp/cron.PublishNsqs")
	defer render.FriendlyEntityError(&err, EntityName)
	res = &messageGrpc.CronRes{}

	var limit int32 = 10
	var nsqPubIDCurrent int64
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		nsqSubPtrs, err := s.entityHub.NsqService.ListNsqSubPtrsWithLock(ctx, q, limit)
		if err != nil {
			return
		}
		for _, nsqSubPtr := range nsqSubPtrs {
			nsqPubIDCurrent = nsqSubPtr.ID
			switch nsqSubPtr.Topic {
			case nsqMall.GetOrderCancelTopic():
				ptr := &nsqMall.OrderCancelNotification{}
				err = json.Unmarshal(nsqSubPtr.Message, ptr)
				if err != nil {
					return
				}
				err = s.comHub.NsqMallService.HandleOrderCancel(ctx, q, ptr)
				if err != nil {
					return
				}
				err = s.entityHub.NsqService.MarkNsqSubHandleSuccess(ctx, q, nsqPubIDCurrent)
				if err != nil {
					return
				}
				s.slog.Infof("webrpc-外部交易(%s)-订单(%d)解锁会员优惠券 ok", ptr.OutTransNo, ptr.OutOrderNo)
			case nsqPay.GetOrderPayFinishTopic():
				ptr := &nsqPay.OrderPaySuccessNotification{}
				err = json.Unmarshal(nsqSubPtr.Message, ptr)
				if err != nil {
					return
				}
				err = s.comHub.NsqPayService.HandleOrderPayFinish(ctx, q, ptr)
				if err != nil {
					return
				}
				err = s.entityHub.NsqService.MarkNsqSubHandleSuccess(ctx, q, nsqPubIDCurrent)
				if err != nil {
					return
				}
				s.slog.Infof("webrpc-外部交易(%s)使用会员优惠券 ok", ptr.OutTransNo)
			}
		}
		slog.Infof("nsqSubPtrs (%d)条", len(nsqSubPtrs))
		return
	})
	if err != nil {
		s.dao.Q.UpdateNsqSubError(ctx, sqlc.UpdateNsqSubErrorParams{
			ID:     nsqPubIDCurrent,
			ErrMsg: sqlc.NSFromString(err.Error()),
		})
		return
	}
	res.Msg = "ok"
	return
}
